#pragma once
#include "defs/enums.h"
#include "macros/macros.h"
#include "systemc.h"

#include <cstdint>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include "../unit_module/dram_kvtable/dram_kvtable.h"
#include <unordered_set>
#include <sstream>

using namespace std;

// 全局的原语数组
class prim_base;
class chip_instr_base;
extern vector<prim_base *> global_prim_stash;
extern vector<chip_instr_base *> global_chip_prim_stash;

extern int MAX_SRAM_SIZE;
extern int CORE_COMM_PAYLOAD;
extern int CORE_ACC_PAYLOAD;

class DramKVTable;
extern DramKVTable** g_dram_kvtable;

extern sc_event kv_event;
extern int dram_aligned;
extern bool use_gpu;

extern string gpu_dram_config;

// one per system，用于config转msg的消息传递
class AddrLabelTable;
extern AddrLabelTable g_addr_label_table;

// 记录所有在计算原语中的参数，见test文件夹下的config文件
extern vector<pair<string, int>> vtable;

extern u_int64_t data_footprint_in_words;

// 网络拓扑大小
extern int GRID_X;
extern int GRID_Y;
extern int GRID_SIZE;
extern int CORE_PER_SM;
// extern int BOARD_W;

// 模拟模式（数据流/gpu/pd serving）
extern SIM_MODE SYSTEM_MODE;

// 模拟dram数组
#if DUMMY == 1
extern uint32_t *dram_array;
#else
// used for DRAM on cores
// uint32_t *dram_array[GRID_SIZE];
#endif

// dcache相关
#if DCACHE == 1
// u_int16_t * dcache_freq;
extern std::unordered_map<u_int64_t, u_int16_t> dcache_freq_v2;

extern std::unordered_set<uint64_t> *dcache_dirty;
// extern bool **dcache_dirty;
extern uint64_t **dcache_tags;
extern uint32_t *dcache_occupancy;
extern uint32_t *dcache_last_evicted;
#endif

extern u_int64_t dcache_hits;
extern u_int64_t dcache_misses;
extern u_int64_t dcache_evictions;
extern u_int64_t *mc_transactions;
extern u_int64_t *mc_latency;
extern u_int64_t *mc_writebacks;
extern u_int32_t ***frame_counters;

extern bool use_node;
extern bool use_DramSys;
extern bool gpu_inner;
extern float comp_util;
extern bool gpu_clog;
extern int gpu_bw;
extern int gpu_B;
extern string g_config_file;
extern int dram_bw;
extern bool beha_dram;
extern float beha_dram_util;
// extern int DRAM_BURST_BYTE;
// extern int L1CACHELINESIZE;
// extern int L2CACHELINESIZE;
#define RESET "\x1B[0m"  // 重置颜色
#define RED "\x1B[1;31m"   // 红色
#define GREEN "\x1B[1;32m" // 绿色

class ExuConfig;
class SfuConfig;
extern vector<pair<int, ExuConfig *>> tile_exu;
extern vector<pair<int, SfuConfig *>> tile_sfu;
extern vector<pair<int, int>> mem_sram_bw;
extern vector<pair<int, string>> mem_dram_config_str;
extern vector<pair<int, int>> mem_dram_bw;


extern int verbose_level;

// #define LOG_VERBOSE(level, core_id, message) \
//     do { \
//         if (verbose_level >= (level)) { \
//             std::ostringstream __log_stream; \
//             __log_stream << "[INFO] Core " << (core_id) << " " << message; \
//             std::cout << __log_stream.str() << std::endl; \
//         } \
//     } while (0)

// utils/logging.cpp 或 memory_utils.cpp 中添加

const char* get_core_color(int core_id);
void close_log_files();
void log_verbose_impl(int level, int core_id, const std::string& message);
extern std::unordered_map<int, std::ofstream*> log_streams;


#define LOG_VERBOSE(level, core_id, message) \
    do { \
        if (verbose_level >= (level)) { \
            std::ostringstream __oss; \
            __oss << message; \
            log_verbose_impl(level, core_id, __oss.str()); \
        } \
    } while (0)

// #define LOG_VERBOSE(level, core_id, message) \
//     do { \
//         if (verbose_level >= (level)) { \
//             std::ostringstream __log_stream; \
//             const char* color = get_core_color(core_id); \
//             __log_stream << color << "[INFO] Core " << (core_id) << " " << message << "\033[0m"; \
//             // __log_stream << "[INFO] Core " << (core_id) << " " << message; \
//             std::string log_msg = __log_stream.str(); \
//             /* 控制台输出 */ \
            
//             std::cout << log_msg << std::endl; \
//             /* 文件输出 */ \
//             auto it = log_streams.find((core_id)); \
//             if (it == log_streams.end()) { \
//                 std::string filename = "core_" + std::to_string(core_id) + ".log"; \
//                 log_streams[core_id] = new std::ofstream(filename, std::ios::app); \
//                 *log_streams[core_id] << "-- New Session --\n"; \
//             } \
//             *log_streams[core_id] << log_msg << std::endl; \
//         } \
//     } while (0)

// #define LOG_VERBOSE(level, core_id, message) \
//     do { if (verbose_level >= (level)) std::cout << "[INFO] Core " << (core_id) << " " << (message) << std::endl; } while(0)
